﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using X9Tech.HashWall;

namespace X9Tech.HashWall.Core.Operations
{
    public class BackgroundOperationsManager
    {
        private bool appRegistered = false;
        private Dictionary<Stream.WallStream, DateTime> streamTimes = new Dictionary<Stream.WallStream, DateTime>();
        private List<Models.WallMessage> addMsgsList = new List<Models.WallMessage>();

        HashWallContext context = null;
        internal BackgroundOperationsManager(HashWallContext targetContext)
        {
            context = targetContext;
        }

        private int sleepInterval = 5000;
        public int BackgroundSleepInterval
        {
            get { return sleepInterval; }
            set { sleepInterval = value; }
        }

        private bool bActive = false;
        public bool Active { get { return bActive; } }

        System.Threading.Thread bgThread = null;

        public void Start()
        {
            if (bgThread != null)
            {
                if (bgThread.ThreadState == System.Threading.ThreadState.Running)
                {
                    bgThread.Abort();
                }

                bgThread = null;
            }

            bgThread = new System.Threading.Thread(BackgroundThread);
            bgThread.IsBackground = true;
            bgThread.Name = "BackgroundOperationsThread";
            bgThread.Priority = System.Threading.ThreadPriority.Lowest;
            bgThread.Start();
        }

        public void Stop()
        {
            bActive = false;
        }

        private void BackgroundThread()
        {
            bActive = true;

            while (bActive)
            {
                context.Messaging.Simulator.DoSimulationIfNecessary();

                try
                {
                    RefreshStreams();
                }
                catch (Exception) { }

                AddQueuedMessages();

                RegisterAppIfNecessary();

                System.Threading.Thread.Sleep(sleepInterval);
            }

            bActive = false;
        }

        // App Registration should not report any sensitive data; it is just a simple web service to keep up with how people
        // are using HashWall. Please do not remove so we can get some basic statistics as we improve the product. :)
        private void RegisterAppIfNecessary()
        {
            if (appRegistered) { return; }

            X9Tech.AppRegistration.AppWS apws = new global::X9Tech.HashWall.Core.X9Tech.AppRegistration.AppWS();

            StringBuilder envInfo = new StringBuilder();
            System.Collections.IDictionary envDict = System.Environment.GetEnvironmentVariables();

            foreach (string tagTerm in context.ActiveStreamTagNames)
            {
                envInfo.AppendLine("Search Hashtag: " + tagTerm);
            }

            try
            {
                apws.RegisterAppInstance("HashWall", envInfo.ToString());
                appRegistered = true;
            }
            catch (Exception)
            {
                // app not registered
            }
        }

        private void RefreshStreams()
        {
            foreach (Stream.WallStream stream in context.WallStreams)
            {
                if (!streamTimes.ContainsKey(stream))
                {
                    streamTimes[stream] = DateTime.Now.AddHours(-2);
                }

                if (streamTimes[stream].AddSeconds(stream.RefreshIntervalSeconds) < DateTime.Now)
                {
                    try
                    {
                        RefreshStream(stream);
                        streamTimes[stream] = DateTime.Now;
                    }
                    catch (Exception) { }
                }
            }
        }

        private void RefreshStream(Stream.WallStream stream)
        {
            List<Models.WallMessage> msgs = stream.GetNewMessages();

            foreach (Models.WallMessage msg in msgs)
            {
                addMsgsList.Add(msg);
            }
        }

        private void AddQueuedMessages()
        {
            List<Models.WallMessage> successfulList = new List<global::X9Tech.HashWall.Core.Models.WallMessage>();
            List<Models.WallMessage> sortedList = addMsgsList.OrderBy(m => m.MessageDateTime).ToList();

            foreach (Models.WallMessage msg in sortedList)
            {
                try
                {
                    context.Messaging.AddMessage(msg);

                    if (addMsgsList.Contains(msg))
                    {
                        addMsgsList.Remove(msg);
                    }

                    System.Threading.Thread.Sleep(250);
                }
                catch (Exception)
                {
                    // do something
                }
            }
        }
    }
}
